package com.xujl.fastlib.http;


import com.xujl.fastlib.R;
import com.xujl.fastlib.base.BaseConfig;
import com.xujl.fastlib.base.IControl;
import com.xujl.fastlib.base.IStateLayout;
import com.xujl.fastlib.utils.ConfigManager;
import com.xujl.fastlib.utils.LogS;
import com.xujl.fastlib.utils.ResUtils;
import com.xujl.fastlib.utils.StringUtils;
import com.xujl.fastlib.utils.ToastUtils;
import com.xujl.fastlib.window.LoadingWindow;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.SocketTimeoutException;
import java.util.List;

import io.reactivex.observers.DisposableObserver;

/**
 * Created by goldze on 2017/5/10.
 * 统一的Code封装处理。该类仅供参考，实际业务逻辑, 根据需求来定义，
 */

public abstract class ApiDisposableObserver<T> extends DisposableObserver<BaseResponse<T>> implements Subscriber<BaseResponse<T>> {
    private static final String TAG = "ApiDisposableObserver";
    private IControl mControl;
    private boolean enableLoading = false;
    private boolean enableLoadingDialog = true;
    private LoadingWindow mLoadingWindow;

    public ApiDisposableObserver (IControl control) {
        mControl = control;
        Type superclass = getClass().getGenericSuperclass();
        if (superclass instanceof Class) {

        } else {
            ParameterizedType parameterized = (ParameterizedType) superclass;
            try {
                Class<List> cls = (Class<List>) parameterized.getActualTypeArguments()[0];
            } catch (Exception e) {
                enableLoading = false;
            }
        }

    }

    public abstract void onResult (BaseResponse<T> response, T data);

    public void onResultFailed (String code, String msg) {
        if (mControl != null) {
            mControl.exposeView().toast(code + ":" + msg);
        } else {
            ToastUtils.toast(code + ":" + msg);
        }
    }

    public ApiDisposableObserver<T> setEnableLoading (boolean enableLoading) {
        this.enableLoading = enableLoading;
        return this;
    }

    public ApiDisposableObserver<T> setEnableLoadingDialog (boolean enableLoadingDialog) {
        this.enableLoadingDialog = enableLoadingDialog;
        return this;
    }

    @Override
    public void onComplete () {

    }

    @Override
    public void onSubscribe (Subscription s) {

    }

    @Override
    public void onError (Throwable e) {
        e.printStackTrace();
        if (e instanceof ResponseThrowable) {
            ResponseThrowable rError = (ResponseThrowable) e;
            LogS.d(TAG, rError.message);
        }
        showError();
        if (e instanceof CommitException) {
            final String code = ((CommitException) e).getCode();
            final String desc = ((CommitException) e).getDesc();
            if (StringUtils.equals(code, CodeRule.CODE_TOKEN_ERROR)) {
                ConfigManager.getInstance().doLoginInvalid(code, desc);
//            onResult(response, response.getData());
                onResultFailed(code, desc);
                return;
            }
            onResultFailed(((CommitException) e).getCode(), ((CommitException) e).getDesc());
            return;
        }
        try {
            if (e instanceof JsonParseException) {
                onResultFailed(CodeRule.CODE_JSON_ERROR, ((JsonParseException) e).getJson());
                return;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            onResultFailed(CodeRule.CODE_UNKNOW, ex.getMessage());
            return;
        }

        //其他全部甩锅网络异常

        if (e instanceof SocketTimeoutException) {
            onResultFailed(CodeRule.CODE_NETWORK_ERROR, ResUtils.getString(R.string.network_error));
            return;
        }
        onResultFailed(CodeRule.CODE_UNKNOW, e.getMessage());
    }

    @Override
    public final void onStart () {
        super.onStart();
        onStart(this);
        showLoading();
        // if  NetworkAvailable no !   must to call onCompleted
        if (!NetworkUtil.isNetworkAvailable(BaseConfig.getContext())) {
            LogS.d(TAG, "无网络，读取缓存数据");
            showError();
            onResultFailed(CodeRule.CODE_NETWORK_ERROR, ResUtils.getString(R.string.no_network));
        }
    }

    public void onStart (ApiDisposableObserver observer) {

    }

    @Override
    public void onNext (BaseResponse<T> response) {
        dismissLoadingDialog();
        if (response == null) {
            showEmpty();
            onResultFailed(CodeRule.CODE_DATA_NULL, ResUtils.getString(R.string.no_response));
            return;
        }
        if (StringUtils.equals(response.getCode(), CodeRule.CODE_200)) {
            showSuccess();
            //请求成功, 正确的操作方式
            onResult(response, (T) response.getData());
            return;
        }
        if (StringUtils.equals(response.getCode(), CodeRule.CODE_TOKEN_ERROR)) {
            ConfigManager.getInstance().doLoginInvalid(response.getCode(), response.getDescription());
//            onResult(response, response.getData());
            onResultFailed(response.getCode(), response.getDescription());
            return;
        }
        showError();
        onResultFailed(response.getCode(), response.getDescription());
    }

    private void showLoading () {
        if (enableLoading) {
            mControl.exposeView().showState(IStateLayout.TYPE_LOADING);
            return;
        }
        showLoadingDialog();
    }

    private void showEmpty () {
        if (enableLoading) {
            mControl.exposeView().showState(IStateLayout.TYPE_EMPTY);
            return;
        }
        dismissLoadingDialog();
    }

    private void showSuccess () {
        if (enableLoading) {
            mControl.exposeView().showState(IStateLayout.TYPE_SUCCESS);
            return;
        }
        dismissLoadingDialog();
    }

    private void showError () {
        if (enableLoading) {
            mControl.exposeView().showState(IStateLayout.TYPE_ERROR);
            return;
        }
        dismissLoadingDialog();
    }

    private void showLoadingDialog () {
        if (!enableLoadingDialog) {
            return;
        }
        if (mLoadingWindow != null) {
            mLoadingWindow.showPopupWindow();
            return;
        }
        if (mControl != null) {
            mLoadingWindow = mControl.exposeView().showLoadingWindow();
            return;
        }
        mLoadingWindow = new LoadingWindow(ConfigManager.getInstance().getContext());
        mLoadingWindow.showPopupWindow();
    }

    private void dismissLoadingDialog () {
        if (!enableLoadingDialog) {
            return;
        }
        if (mLoadingWindow != null) {
            mLoadingWindow.dismiss();
        }
    }

    public IControl getControl () {
        return mControl;
    }

    public static final class CodeRule {
        //===========================服务器返回码
        //请求成功, 正确的操作方式
        public static final String CODE_200 = "000000";
        //登录失效
        public static final String CODE_TOKEN_ERROR = "000009";
        //========================本地异常
        public static final String CODE_NETWORK_ERROR = "999L";//网络相关异常
        public static final String CODE_UNKNOW = "998L";//未知异常
        public static final String CODE_997 = "997L";
        public static final String CODE_DATA_NULL = "996L";//获取到的数据为空
        public static final String CODE_JSON_ERROR = "995L";//json解析出错
    }
}